//
//  BackgroundDownloadManager.m
//  MyProject
//
//  Created by yun on 2018/4/23.
//  Copyright © 2018年 yun. All rights reserved.
//

#import "BackgroundDownloadManager.h"
#import <CommonCrypto/CommonDigest.h>
#import "AppDelegate.h"

@interface BackgroundDownloadManager ()<NSURLSessionDownloadDelegate>

@property (nonatomic,strong) NSURLSessionDownloadTask *loadTask;
@property (nonatomic,strong) NSData *loadData;

@end

static NSString * const BackgroundDownloadSessionIdentifier = @"BackgroundDownloadSessionIdentifier";

@implementation BackgroundDownloadManager

+ (instancetype)sharedBackgroundDownloadManager{
    static BackgroundDownloadManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

+ (NSURLSession *)backgroundSession{
    static NSURLSession *session;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:BackgroundDownloadSessionIdentifier];
        config.discretionary = YES;
        session = [NSURLSession sessionWithConfiguration:config delegate:[self sharedBackgroundDownloadManager] delegateQueue:[NSOperationQueue new]];
    });
    return session;
}

#pragma mark -- method
// 创建下载任务并下载
- (void)startDownloadTaskWithURL:(NSString *)url{
    // [NSURL URLWithString:@"http://sw.bos.baidu.com/sw-search-sp/software/bd15545b3c092/QQ_mac_6.3.0.dmg"]
    NSURLSession *session = [BackgroundDownloadManager backgroundSession];
    NSURLSessionDownloadTask *loadTask = [session downloadTaskWithURL:[NSURL URLWithString:url]];
    self.loadTask = loadTask;
    [loadTask resume];
}
// 取消下载
- (void)cancelDownloadTask{
    
    [self.loadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
//        self.loadData = resumeData;
    }];
}
// 继续下载
- (void)continueDownloadTaskWithUrl:(NSString *)url{
    if (!self.loadData && url.length > 0) {
        self.loadData = [self getResumeDataWithUrl:url];
    }
    if (self.loadData) {
        self.loadTask = [[BackgroundDownloadManager backgroundSession] downloadTaskWithResumeData:self.loadData];
        [self.loadTask resume];
        self.loadData = nil;// 取缓存数据的标志
    }
}


// 文件下载路径
- (NSString *)filePathWithURL:(NSString *)url{
    NSString *fPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self mdFileNameForKey:url]];
    return fPath;
}

// MD5加密
- (nullable NSString *)mdFileNameForKey:(nullable NSString *)key {
    const char *str = key.UTF8String;
    if (str == NULL) {
        str = "";
    }
    unsigned char r[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, (CC_LONG)strlen(str), r);
    NSURL *keyURL = [NSURL URLWithString:key];
    NSString *ext = keyURL ? keyURL.pathExtension : key.pathExtension;
    NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%@",
                          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10],
                          r[11], r[12], r[13], r[14], r[15], ext.length == 0 ? @"" : [NSString stringWithFormat:@".%@", ext]];
    return filename;
}

// 保存data
- (void)saveResumeData:(NSData *)resumeData url:(NSString *)url{
    
    NSString *path =  [self filePathWithURL:[NSString stringWithFormat:@"data%@",url]];
    [resumeData writeToFile:path atomically:YES];
}

// 取出保存的data
- (NSData *)getResumeDataWithUrl:(NSString *)url{
    NSString *path = [self filePathWithURL:[NSString stringWithFormat:@"data%@",url]];
    if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
        return [[NSData alloc] initWithContentsOfFile:path];
    }
    return nil;
}

- (void)checkFileExist:(NSString *)url{
    NSString *path = [self filePathWithURL:url];
    if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
        NSLog(@"文件存在");
        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
        
    } else {
        NSLog(@"文件不存在");
    }
}

#pragma mark -- 代理

// 告诉代理该任务完成传输数据。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error{
    NSLog(@"%@",error);
    if (error) {
        if ([error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]) {
            NSData *resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];
            //保存下载的data,下次启动程序再次下载
            if (resumeData) {
                [self saveResumeData:resumeData url:task.currentRequest.URL.absoluteString];
            }
        }
    }
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
    NSLog(@"下载完成");
    
    NSString *path = [self filePathWithURL:downloadTask.currentRequest.URL.absoluteString];
    [[NSFileManager defaultManager] moveItemAtPath:location.path toPath:path error:nil];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    
    NSLog(@"======下载进度：%.2f%%======",100.f*totalBytesWritten/totalBytesExpectedToWrite);
    
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
    
    NSLog(@"恢复下载");
}

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
    dispatch_async(dispatch_get_main_queue(), ^{
        AppDelegate *appDelegate = (AppDelegate *)([[UIApplication sharedApplication] delegate]);
        
        if (appDelegate.bgSessionCompletionHandler) {
            
            void (^completionHandler)(void) = appDelegate.bgSessionCompletionHandler;
            
            appDelegate.bgSessionCompletionHandler = nil;
            
            completionHandler();
            
        }
    });

}


@end
